package com.rxh.trade;

import com.fasterxml.jackson.databind.JsonNode;
import com.rxh.pojo.cross.AllinPayNotify;
import com.rxh.pojo.cross.BankResult;
import com.rxh.pojo.payment.Refund;
import com.rxh.pojo.payment.Trade;
import com.rxh.utils.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: 陈俊雄
 * Date: 2018/10/8
 * Time: 17:08
 * Project: Management
 * Package: com.rxh.trade
 */
@Component
public class AllinPay implements AcquirerInterface<AllinPayNotify> {
    // private final static ResourceBundle bundle = ResourceBundle.getBundle("allinpay");// allinpay配置属性文件
    // private AllinPayUtils APUtils = new AllinPayUtils();
    Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${AllinPay.id}")
    private Integer acquirerId;
    @Value("${AllinPay.payNotifyUrl}")
    private String payNotifyUrl;
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");

    @Override
    public Integer getAcquirerId() {
        return acquirerId;
    }

    @Override
    public BankResult trade(Trade trade) {
        JsonNode jsonNode = JsonUtils.json2JsonNode(trade.getCoreAcquirerAccount().getParams());
        Map<String, String> param = new HashMap<String, String>();
        param.put("inputCharset", "1");// 字符集编码，默认1表示UTF-8 2 GBK
        param.put("pickupUrl", "http://www.rxhpay.com");// 支付跳转地址
        param.put("receiveUrl", payNotifyUrl);// 支付通知地址
        param.put("version", "v1.0");// 版本
        param.put("language", "3");// 语言，固定值：3；
        // 国际卡支付页面语言根据访问浏览器自动选择语言，目前支持：英文、简体中文、繁体中文
        param.put("signType", "0");// 0表示订单上送和交易结果通知都使用MD5进行签名,1表示商户用使用MD5算法验签上送订单，通联交易结果通知使用证书签名
        param.put("merchantId", jsonNode.get("merno").asText());// 商户在通联申请开户的商户号
        param.put("payerName", trade.getTradeObject().getBillLastName() + " " + trade.getTradeObject().getBillFirstName());// 付款人姓名
        param.put("payerEmail", trade.getTradeObject().getBillEmail());// 付款人邮件联系方式
        param.put("payerTelephone", trade.getTradeObject().getBillPhone());// 付款人电话联系方式
        // param.put("orderNo", trade.getCoreOrder().getId().toString());// 商户订单号
        param.put("orderAmount", trade.getChannelOrderInfo().getChannelAmount().toString());// 商户订单金额
        //param.put("orderDatetime", dateFormat.format(trade.getCoreOrder().getTradeTime()));// 商户订单提交时间


        return null;
    }

    @Override
    public String tradeNotify(AllinPayNotify notify) {

        /*String result;
        // 商品信息
        Map<String, String> NotifyParam = new HashMap<String, String>();
        NotifyParam.put("merchantId", req.getParameter("merchantId"));
        NotifyParam.put("version", req.getParameter("version"));
        NotifyParam.put("language", req.getParameter("language"));
        NotifyParam.put("signType", req.getParameter("signType"));
        NotifyParam.put("payType", req.getParameter("payType"));
        NotifyParam.put("issuerId", req.getParameter("issuerId"));
        NotifyParam.put("paymentOrderId", req.getParameter("paymentOrderId"));
        NotifyParam.put("orderNo", req.getParameter("orderNo"));
        NotifyParam.put("orderDatetime", req.getParameter("orderDatetime"));
        NotifyParam.put("orderAmount", req.getParameter("orderAmount"));
        NotifyParam.put("payDatetime", req.getParameter("payDatetime"));
        NotifyParam.put("payAmount", req.getParameter("payAmount"));
        NotifyParam.put("ext1", req.getParameter("ext1"));
        NotifyParam.put("ext2", req.getParameter("ext2"));
        NotifyParam.put("payResult", req.getParameter("payResult"));
        NotifyParam.put("errorCode", req.getParameter("errorCode"));
        NotifyParam.put("returnDatetime", req.getParameter("returnDatetime"));
        NotifyParam.put("signMsg", req.getParameter("signMsg"));
        // 通知MD5签名串拼接
        String MD5Info = APUtils.getValue(NotifyParam, "merchantId") + APUtils.getValue(NotifyParam, "version")
                + APUtils.getValue(NotifyParam, "language") + APUtils.getValue(NotifyParam, "signType")
                + APUtils.getValue(NotifyParam, "payType") + APUtils.getValue(NotifyParam, "issuerId")
                + APUtils.getValue(NotifyParam, "paymentOrderId") + APUtils.getValue(NotifyParam, "orderNo")
                + APUtils.getValue(NotifyParam, "orderDatetime") + APUtils.getValue(NotifyParam, "orderAmount")
                + APUtils.getValue(NotifyParam, "payDatetime") + APUtils.getValue(NotifyParam, "payAmount")
                + APUtils.getValue(NotifyParam, "ext1") + APUtils.getValue(NotifyParam, "ext2") + APUtils.getValue(NotifyParam, "payResult")
                + APUtils.getValue(NotifyParam, "errorCode") + APUtils.getValue(NotifyParam, "returnDatetime");
        MD5Info = MD5Info + "key=" + bundle.getString("allinPay_md5");
        // 商品信息进行MD5加密
        String MD5info = DigestUtils.md5Hex(MD5Info).toUpperCase();
        logger.info("AllinPay通知请求参数：" + NotifyParam);
        if (MD5info.equals(req.getParameter("signMsg"))){
            String NotifySignMag = DigestUtils.md5Hex( req.getParameter("orderNo")+ bundle.getString("md5_key") + "check");//orderNo
            String sendUrl = bundle.getString("payment_url") + "banknotice?action=check&orderId=" + req.getParameter("orderNo")

                    + "&sign=" + NotifySignMag;
            JSONObject checkResult = JSON.parseObject(HttpClientUtils.get(HttpClientUtils.createHttpClient(), sendUrl));
        }

        return result;*/
        return null;
    }


    @Override
    public BankResult tradeQuery(Trade trade) {
     /*   Map<String, String> querydata = new HashMap<String, String>();
        querydata.put("merchantId", trade.getCoreorder().getMerId().toString());
        querydata.put("version", "v1.5");
        querydata.put("signType", "0");
        querydata.put("orderNo", trade.getCoreOrderDetail().getOrderId().toString());
        querydata.put("orderDatetime", trade.getCoreorder().getTradeTime().toString());
        querydata.put("queryDatetime", dateFormat.format(new Date()));

        //查询交易信息MD5签名串拼接
        String MD5Info=APUtils.getValue(querydata,"merchantId")+APUtils.getValue(querydata,"version")+APUtils.getValue(querydata,"signType")
                +APUtils.getValue(querydata,"orderNo")+APUtils.getValue(querydata,"orderDatetime")+APUtils.getValue(querydata,"queryDatetime");
        MD5Info = DigestUtils.md5Hex(MD5Info + "pkey=" + bundle.getString("allinPay_md5")).toUpperCase();
        querydata.put("signMsg", MD5Info);
        String content = HttpClientUtils.post(HttpClientUtils.createHttpClient(), bundle.getString("allinPay_query_url"), querydata, UTF_8);
        logger.info("查询返回参数：" + content);
        return content;*/
        return null;
    }

    @Override
    public BankResult tradeListQuery(Trade trade) {
        return null;
    }

    @Override
    public BankResult refund(Refund refund) {
        JsonNode bankParam = JsonUtils.json2JsonNode(refund.getCoreAcquirerAccount().getParams());
        // 转换时间格式
        Long orderDate = Long.parseLong(refund.getOrder().getTradeTime().toString());
        Timestamp dateString = new Timestamp(orderDate);
        String orderDatetime = dateFormat.format(dateString);

        Map<String, String> RefundParam = new HashMap<String, String>();
        RefundParam.put("version", "v2.3");
        RefundParam.put("signType", "0");// 固定值：0，0表示用md5签名
        RefundParam.put("merchantId", bankParam.get("merno").textValue());// 商户号
        RefundParam.put("orderNo", refund.getOrder().getId().toString());
        RefundParam.put("refundAmount", refund.getCoreOrderChange().getRmbAmount().toString());
        RefundParam.put("orderDatetime", orderDatetime);
        RefundParam.put("mchtRefundOrderNo", refund.getOrder().getBankOrderId());

        // 退款请求MD5串拼接
        String RefundMD5 = "";
        // RefundMD5 = RefundMD5 + "key=" + bundle.getString("allinPay_md5");
        RefundParam.put("signMsg", DigestUtils.md5Hex(RefundMD5).toUpperCase());

        logger.info("退款请求参数：" + RefundParam);
        logger.info("send_url：" + bankParam.get("refundUrl"));
        String content = HttpClientUtils.doPost(HttpClientUtils.getHttpsClient(), "refundUrl",
                RefundParam);

        logger.info("退款response result:" + content);

        Map<String, String> result = new HashMap<String, String>();// 返回结果
        for (String item : content.split("&")) {
            String[] entry = item.split("=");
            result.put(entry[0], entry.length == 2 ? entry[1] : "");
        }

        // 返回MD5信息
        String signMsg = result.get("signMsg");
        String payResult = result.get("refundResult");// 退款结果
        BankResult bankResult = new BankResult();// 获取银行返回结果对象
        String bankCode;
        // 退款返回MD5信息拼接
        String ReturnMD5 =
                "";
        // ReturnMD5 = ReturnMD5 + "key=" + bundle.getString("allinPay_md5");

        // 判断数据是正常返回还是只返回了错误编码和错误信息
        if (null == payResult || payResult.isEmpty()) {
            bankResult.setStatus(SystemConstant.CHANGE_BANK_STATUS_FAIL);
            bankResult.setBankResult("退款申请失败：" + result.get("ERRORMSG"));
            try {
                bankCode = BankResultInfoCode.CommunicateCodeTwo.valueOf(result.get("ERRORCODE")).getStatusMsg();
            } catch (Exception e) {
                logger.info("AllinPay未定义的错误信息,错误编码为：" + result.get("errorCode"));
                bankCode = "error.5000";
            }
            bankResult.setBankCode(bankCode);
            bankResult.setParam(content);
            logger.info("退款申请失败:原因是" + result.get("ERRORCODE") + result.get("ERRORMSG"));
        } else {
            // 签名验证
            if (DigestUtils.md5Hex(ReturnMD5).toUpperCase().equals(signMsg)) {
                if ("20".equals(payResult)) {// 银行状态
                    bankResult.setStatus(SystemConstant.CHANGE_BANK_STATUS_APPLICATION_SUCCESS);
                    bankResult.setBankResult("退款申请成功");
                    logger.info("退款申请成功");
                } else {
                    bankResult.setStatus(SystemConstant.CHANGE_BANK_STATUS_FAIL);
                    bankResult.setBankResult("退款申请失败：" + result.get("errorCode"));
                    try {
                        bankCode = BankResultInfoCode.CommunicateCodeTwo.valueOf("A" + result.get("errorCode"))
                                .getStatusMsg();
                    } catch (Exception e) {
                        logger.info("AllinPay未定义的错误信息,错误编码为：" + result.get("errorCode"));
                        bankCode = "error.5000";
                    }
                    bankResult.setBankCode(bankCode);
                    logger.info("退款申请失败");
                }
                bankResult.setTime(new Date());// 处理完成时间
                bankResult.setParam(content);// 银行返回字符串
            } else {
                logger.info("MD5验证失败");
                bankResult.setStatus(SystemConstant.CHANGE_BANK_STATUS_FAIL);
            }

        }

        String rspString = JsonUtils.objectToJson(bankResult);
        logger.info("退款申请返回payment信息：" + rspString);
        return bankResult;

    }

    @Override
    public String refundNotify(AllinPayNotify notify) {
        return null;
    }


    @Override
    public BankResult refundQuery(Refund refund) {
        return null;
    }

    @Override
    public BankResult refundListQuery(Refund refund) {
        return null;
    }


}
